﻿#if _MSC_VER >= 1600
#pragma execution_character_set("utf-8")
#endif

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>

#define qout qDebug()

void MainWindow::sysInit()
{
    //发送消息定时器，用于循环发送
    Send_timer = new QTimer(this);
    connect(Send_timer,&QTimer::timeout,this,&MainWindow::LoopSend);
    //绑定消息信号，更新接收区显示

    //!UDP模式收到消息
    UdpThread = new QThread;
    UdpService = new UDP_Service;
    UdpService->moveToThread(UdpThread);
    connect(UdpService,&UDP_Service::UdpModeMsg,this,&MainWindow::UpdateMsg);
    connect(UdpService,&UDP_Service::BindSuccess,this,&MainWindow::Disable_Options);
    connect(this,&MainWindow::udp_open,UdpService,&UDP_Service::OpenUdp);
    connect(this,&MainWindow::udp_close,UdpService,&UDP_Service::CloseUdp);
    connect(this,&MainWindow::udp_send,UdpService,&UDP_Service::SendUdpMsg);

    //!TCP客户端模式收到消息
    ClientThread = new QThread;
    TcpClient = new TCP_Client;
    TcpClient->moveToThread(ClientThread);
    connect(TcpClient,&TCP_Client::TcpClientModeMsg,this,&MainWindow::UpdateMsg);
    connect(TcpClient,&TCP_Client::ConnectionBuilt,this,&MainWindow::Disable_Options);
    connect(TcpClient,&TCP_Client::ConnectionClosed,this,&MainWindow::Enable_Options);
    connect(this,&MainWindow::tcpC_connect,TcpClient,&TCP_Client::ConnectToServer);
    connect(this,&MainWindow::tcpC_disconnect,TcpClient,&TCP_Client::DisconnectFromServer);
    connect(this,&MainWindow::tcpC_send,TcpClient,&TCP_Client::SendMessage);

    //!TCP服务器模式：消息通知
    ServerThread = new QThread;
    TcpServer = new TCP_Server;
    TcpServer->moveToThread(ServerThread);
    connect(this,&MainWindow::tcpS_open,TcpServer,&TCP_Server::StartListen);
    connect(this,&MainWindow::tcpS_close,TcpServer,&TCP_Server::StopListen);
    connect(this,&MainWindow::tcpS_send,TcpServer,&TCP_Server::SendMessage);
    connect(this,&MainWindow::tcpS_kick,TcpServer,&TCP_Server::KickClient);
    //TCP服务器接收到消息，发出信号ClientsMsgToUI，主窗口更新消息
    connect(TcpServer,&TCP_Server::ClientsMsgToUI,this,&MainWindow::UpdateMsg);
    //更新客户端列表
    connect(TcpServer,&TCP_Server::UpdateClientsToUI,this,&MainWindow::UpdateClientsList);
    //有客户端接入或断开时，TCP_Server发出信号TcpServerMsgToUI
    connect(TcpServer,&TCP_Server::TcpServerMsgToUI,this,&MainWindow::UpdateClientsHint);
    connect(TcpServer,&TCP_Server::ListenStarted,this,&MainWindow::Disable_Options);

}

void MainWindow::uiInit()
{
    Send_Count = 0;
    Recive_Count = 0;

    QFile file(":/qss/psblack.css");
    file.open(QFile::ReadOnly);
    QString styleSheet = QString::fromLatin1(file.readAll());
    QString paletteColor = styleSheet.mid(20, 7);
    qApp->setPalette(QPalette(QColor(paletteColor)));
    qApp->setStyleSheet(styleSheet);

    //QHostInfo::localHostName()主机名
    QString localHostName = QHostInfo::localHostName();
    qout<<"本机名称：" <<localHostName;
    QHostInfo hostInfomation = QHostInfo::fromName(localHostName);
    //hostInfomation.addresses()包含IPV4地址和物理地址，只需要IPV4
    foreach(QHostAddress address,hostInfomation.addresses())
    {
        if(address.protocol() == QAbstractSocket::IPv4Protocol)
        {
            qout <<"本机IP地址：" << address.toString();
            ui->Local_IP->addItem(address.toString());
        }
    }
    ui->Local_IP->addItem("127.0.0.1");
    ui->Obj_IP->setIP("127.0.0.1");

    ui->Send->setEnabled(false);    //发送按钮
    ui->label_6->setVisible(false); //客户端列表label
    ui->client_list->setVisible(false); //TCP客户端列表
    ui->Kick->setVisible(false);    //踢除按钮
    ui->label_2->setVisible(false);
    ui->Local_Port->setVisible(false);  //本地端口
    ui->Disconnect->setEnabled(false);  //断开连接按钮
}


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QList<QHostAddress> hosts = QNetworkInterface::allAddresses();
    qout<<hosts;
    QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
    qout<<interfaces;
    sysInit();
    uiInit();
}

MainWindow::~MainWindow()
{
    if(UdpThread->isRunning())
    {
        UdpThread->quit();
        UdpThread->wait();
    }
    if(ServerThread->isRunning())
    {
        ServerThread->quit();
        ServerThread->wait();
    }
    if(ClientThread->isRunning())
    {
        ClientThread->quit();
        ClientThread->wait();
    }
    UdpService->deleteLater();
    TcpClient->deleteLater();
    TcpServer->deleteLater();
    delete UdpThread;
    delete ServerThread;
    delete ClientThread;
    delete ui;
}

//有客户端接入或断开时UI窗口给出提示
void MainWindow::UpdateClientsHint(QString message)
{
    if(ui->DisplayTime->isChecked())
    {
        ui->Recive_msg->append(QDateTime::currentDateTime().toString("yyyy.MM.dd hh:mm:ss.zzz"));
    }
    ui->Recive_msg->append(message);
}

//域名地址解析槽函数
void MainWindow::lookedUp(const QHostInfo &host)
{
    if (host.error() != QHostInfo::NoError)
    {
     QMessageBox::information(this,"域名解析结果","解析失败，未找到相应IP");
     DnsAnalysisResult = "";
     return;
    }
    for(qint8 i = 0;i < host.addresses().count();i++)
    {
        if(host.addresses().at(i).toString() != "")
        {
            DnsAnalysisResult = host.addresses().at(i).toString();
            break;
        }
    }
}

//点击连接
void MainWindow::on_Connect_clicked()
{
    int localPort = ui->Local_Port->value();
    int objPort = ui->Obj_Port->value();
    QString localAddress = ui->Local_IP->currentText();
    QString objAddress = ui->Obj_IP->getIP();
    switch(ui->Protoclo->currentIndex())
    {
    case 0: //TCP客户端模式
        if(objPort > 0)
        {
            if(!ClientThread->isRunning())
            {
                ClientThread->start();
            }
            emit tcpC_connect(objAddress, objPort);
        }
        else
        {
            QMessageBox::warning(this, "警告", "请输入正确的目标端口号！");
            return;
        }
        break;
    case 1: //TCP服务器模式
        if(localPort > 0)
        {
            if(!ServerThread->isRunning())
            {
                ServerThread->start();
            }
            emit tcpS_open(localAddress, localPort);
            ui->client_list->addItem("All Clients");
        }
        else
        {
            QMessageBox::warning(this, "警告", "请输入正确的本地端口号！");
            return;
        }
        break;
    case 2://UDP
        if(localPort > 0)
        {
            if(!UdpThread->isRunning())
            {
                UdpThread->start();
            }
            emit udp_open(localAddress, localPort);
        }
        else
        {
            QMessageBox::warning(this, "警告", "请输入正确的本地端口号！");
            return;
        }
        break;
    }
}
//点击断开
void MainWindow::on_Disconnect_clicked()
{
    Enable_Options();
    switch(ui->Protoclo->currentIndex())
    {
    case 0:
        //关闭与服务器的连接
        emit tcpC_disconnect();
        break;
    case 1:
        emit tcpS_close();
        //清空客户端列表
        ui->client_list->clear();
        break;
    case 2:
        //关闭UDP服务，删除资源
        emit udp_close();
        break;
    }
}
//点击断开连接后启用项
void MainWindow::Enable_Options()
{
    ui->Protoclo->setEnabled(true);
    ui->Connect->setEnabled(true);
    ui->Disconnect->setEnabled(false);
    ui->Send->setEnabled(false);    //发送按钮
    switch(ui->Protoclo->currentIndex())
    {
    case 0:
        ui->Local_IP->setEnabled(true);
        ui->Obj_IP->setEnabled(true);
        ui->Obj_Port->setEnabled(true);
        break;
    case 1:
        ui->Local_IP->setEnabled(true);
        ui->Local_Port->setEnabled(true);
        ui->Kick->setVisible(false);
        break;
    case 2:
        ui->Local_IP->setEnabled(true);
        ui->Local_Port->setEnabled(true);
        break;
    }
}
//点击连接后禁用项
void MainWindow::Disable_Options()
{
    ui->Protoclo->setEnabled(false);
    ui->Connect->setEnabled(false);
    ui->Disconnect->setEnabled(true);
    ui->Send->setEnabled(true);    //发送按钮
    switch(ui->Protoclo->currentIndex())
    {
    case 0:
        ui->Local_IP->setEnabled(false);
        ui->Obj_IP->setEnabled(false);
        ui->Obj_Port->setEnabled(false);
        break;
    case 1:
        ui->Local_IP->setEnabled(false);
        ui->Local_Port->setEnabled(false);
        ui->Kick->setVisible(true);
        break;
    case 2:
        ui->Local_IP->setEnabled(false);
        ui->Local_Port->setEnabled(false);
        break;
    }
}

//接收消息
void MainWindow::UpdateMsg(QByteArray message)
{
    Recive_Count += message.size();
    ui->Recive_cnt->setText("累计接收：" + QString::number(Recive_Count));
    //如果勾选了时间显示
    if(ui->DisplayTime->isChecked())
    {
        ui->Recive_msg->append(QDateTime::currentDateTime().toString("yyyy.MM.dd hh:mm:ss.zzz\t收"));
    }
    if(ui->HexDisplay->isChecked())//如果勾选了16进制显示
    {
        ui->Recive_msg->append(message.toHex(' '));
    }
    else
    {
        ui->Recive_msg->append(QString::fromLocal8Bit(message));
    }
    if(ui->AutoSwitchLine->isChecked())//如果勾选了换行显示
    {
        ui->Recive_msg->append("");
    }
}
//点击发送
void MainWindow::on_Send_clicked()
{
    //读取当前输入的字符串
    QString StringData = ui->Send_msg->toPlainText();
    //判断是否勾选发送换行
    if(ui->SendNewLine->isChecked())
    {
        StringData += "\r\n";
    }
    QByteArray BytesData = StringData.toLocal8Bit();
    if(ui->HexSend->isChecked())
    {
        BytesData = QByteArray::fromHex(BytesData);
    }
    switch(ui->Protoclo->currentIndex())
    {
    case 0:
        emit tcpC_send(BytesData);
        break;
    case 1:
        emit tcpS_send(ui->client_list->currentText(), BytesData);
        break;
    case 2:
        if(!ui->UdpBroadcast->isChecked())
        {
            emit udp_send(BytesData, ui->Obj_IP->getIP(), ui->Obj_Port->value());
        }
        else
        {
            emit udp_send(BytesData, "255.255.255.255", ui->Obj_Port->value());
        }
        break;
    default:break;
    }
    Send_Count += StringData.length();
    ui->Send_cnt->setText("累计发送：" + QString::number(Send_Count));
    if(ui->DisplayTime->isChecked())
    {
        ui->Recive_msg->append(QDateTime::currentDateTime().toString("yyyy.MM.dd hh:mm:ss.zzz\t发"));
    }
    ui->Recive_msg->append(StringData);
}
//勾选定时发送时，此函数为定时器超时信号的槽
void MainWindow::LoopSend()
{
    on_Send_clicked();
}
//启用定时发送
void MainWindow::on_Timer_Send_clicked()
{
    if(ui->Timer_Send->isChecked())
    {
        if(ui->period->text().toInt() > 0)
        {
            Send_timer->start(ui->period->text().toInt());
        }
        else
        {
            QMessageBox::warning(this, "警告", "定时周期错误！");
        }
    }
    else
    {
        Send_timer->stop();
    }
}
//清空接收区
void MainWindow::on_ClearMessage_clicked()
{
    ui->Recive_msg->clear();
}
//更新客户端列表
void MainWindow::UpdateClientsList(QString method, QString IP)
{
    if(method == "join")
    {
        ui->client_list->addItem(IP);
    }
    else if(method == "leave")
    {
        quint16 index = 0;
        while(ui->client_list->itemText(index) != IP)
        {
            index++;
        }
        ui->client_list->removeItem(index);
    }
    ui->client_list->update();
}

void MainWindow::on_clear_send_cnt_clicked()
{
    Send_Count = 0;
    ui->Send_cnt->setText("累计发送：" + QString::number(Send_Count));
    Recive_Count = 0;
    ui->Recive_cnt->setText("累计接收：" + QString::number(Recive_Count));
}

void MainWindow::on_Protoclo_currentIndexChanged(int index)
{
    switch(index)
    {
    case 0://TCP Client mode
        ui->Connect->setText("连接");
        ui->Disconnect->setText("断开");
        ui->UdpBroadcast->setEnabled(false);

        ui->label_2->setVisible(false);
        ui->Local_Port->setVisible(false);

        ui->label_6->setVisible(false);
        ui->client_list->setVisible(false);

        ui->label_3->setVisible(true);
        ui->Obj_IP->setVisible(true);
        ui->label_4->setVisible(true);
        ui->Obj_Port->setVisible(true);

        ui->Kick->setVisible(false);
        break;
    case 1://TCP Server mode
        ui->Connect->setText("打开");
        ui->Disconnect->setText("关闭");

        ui->label_2->setVisible(true);
        ui->Local_Port->setVisible(true);
        ui->Local_Port->setEnabled(true);

        ui->label_6->setVisible(true);
        ui->client_list->setVisible(true);
        ui->Kick->setVisible(true);
        ui->client_list->clear();

        ui->label_3->setVisible(false);
        ui->Obj_IP->setVisible(false);
        ui->label_4->setVisible(false);
        ui->Obj_Port->setVisible(false);

        ui->UdpBroadcast->setEnabled(false);
        break;
    case 2://UDP mode
        ui->Connect->setText("打开");
        ui->Disconnect->setText("关闭");

        ui->label_2->setVisible(true);
        ui->Local_Port->setVisible(true);
        ui->Local_Port->setEnabled(true);

        ui->label_6->setVisible(false);
        ui->client_list->setVisible(false);
        ui->Kick->setVisible(false);

        ui->label_3->setVisible(true);
        ui->Obj_IP->setVisible(true);
        ui->label_4->setVisible(true);
        ui->Obj_Port->setVisible(true);

        ui->UdpBroadcast->setEnabled(true);
        break;
    }
}

void MainWindow::keyPressEvent(QKeyEvent *key_event)
{
    if(ui->Protoclo->currentIndex() != 1)
    {
        if(key_event->key() == Qt::Key_F1)
        {
            QMessageBox::information(this,"友情提示！" ,"兄弟做nm的白日梦呢？赶紧滚去写代码！" );
        }
    }
    if(key_event->key() == Qt::Key_Escape)
    {
        QMessageBox Mbox;
        Mbox.setWindowTitle("确认窗口" );
        Mbox.setText("确定退出吗？" );
        //Mbox添加按钮yes/no
        Mbox.addButton(QMessageBox::No);
        Mbox.addButton(QMessageBox::Yes);
        //执行Mbox
        Mbox.exec();
        if(Mbox.result() == QMessageBox::Yes)
        {
            this->close();
        }
    }
}
/*-----------------------------------------------------------------------------------------------------------------*/
void MainWindow::on_ActRecivceFont_triggered()  //设置接收区字体
{
    bool ok;
    QFont font = QFontDialog::getFont(&ok, QFont("Times", 12), this);
    if(ok)
    {
        ui->Recive_msg->setFont(font);
    }
}

void MainWindow::on_ActSendFont_triggered() //设置发送区字体
{
    bool ok;
    QFont font = QFontDialog::getFont(&ok, QFont("Times", 12), this);
    if(ok)
    {
        ui->Send_msg->setFont(font);
    }
}

void MainWindow::on_ActOpenFile_triggered()
{
    QString file_path = QFileDialog::getOpenFileName(this,"请选择txt文件","","Text files (*.txt)");
    if(file_path.isEmpty())
    {
        QMessageBox::warning(0,"提示","未选择文件");
        return;
    }
    else
    {
        qout<<file_path;
        QFile txt_file(file_path);
        if (!txt_file.open(QIODevice::ReadOnly | QIODevice::Text))
        {
            QMessageBox::warning(0,"错误：",QString("打开文件失败"));
        }
        else
        {
            ui->Send_msg->setText(txt_file.readAll());
            txt_file.close();
        }
    }
}

void MainWindow::on_ActSaveFile_triggered()
{
    QString fileName = QFileDialog::getSaveFileName();
    QFile file(fileName);
    if (file.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate))
    {
        file.write(ui->Recive_msg->toPlainText().toLocal8Bit());
        file.close();
        QMessageBox::information(0,"提示！","保存成功！");
    }
    else
    {
        QMessageBox::warning(0,"错误！","写入文件失败！");
    }
}

//TCP Server模式下断开客户端连接
void MainWindow::on_Kick_clicked()
{
    if(ui->client_list->count() > 1)
    {
        QString ip = ui->client_list->currentText();
        emit tcpS_kick(ip);
        if(ip.startsWith("All"))
        {
            ui->client_list->clear();
            ui->client_list->addItem("All Clients");
        }
    }
}

void MainWindow::on_ActAbout_triggered()
{
    QMessageBox::information(0,"关于","作者CSDN主页：https://blog.csdn.net/wwplh5520370\n企鹅微信：784765727");
}

void MainWindow::on_ActSkinBlue_triggered()
{
    QFile file(":/qss/lightblue.css");
    file.open(QFile::ReadOnly);
    QString styleSheet = QString::fromLatin1(file.readAll());
    QString paletteColor = styleSheet.mid(20, 7);
    qApp->setPalette(QPalette(QColor(paletteColor)));
    qApp->setStyleSheet(styleSheet);
}

void MainWindow::on_ActSkinWhite_triggered()
{
    QFile file(":/qss/flatwhite.css");
    file.open(QFile::ReadOnly);
    QString styleSheet = QString::fromLatin1(file.readAll());
    QString paletteColor = styleSheet.mid(20, 7);
    qApp->setPalette(QPalette(QColor(paletteColor)));
    qApp->setStyleSheet(styleSheet);
}

void MainWindow::on_ActSkinBlack_triggered()
{
    QFile file(":/qss/psblack.css");
    file.open(QFile::ReadOnly);
    QString styleSheet = QString::fromLatin1(file.readAll());
    QString paletteColor = styleSheet.mid(20, 7);
    qApp->setPalette(QPalette(QColor(paletteColor)));
    qApp->setStyleSheet(styleSheet);
}
